package com.google.code.p.restrpc.http;

import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

public class DefaultHttpClientFactory implements HttpClientFactory {
    
    public static final Log logger = LogFactory.getLog(DefaultHttpClientFactory.class);
    
    private Properties properties;
    
    public DefaultHttpClientFactory() {
    }
    
    public DefaultHttpClientFactory(Properties properties) {
        this.properties = properties;
    }
    
    /*
     * (non-Javadoc)
     */
    public HttpClient getSingleThreadHttpClient() {
        return new DefaultHttpClient();
    }
    
    /*
     * (non-Javadoc)
     */
    public HttpClient getHttpClient() {
        if (properties != null) {
            return getHttpClient(properties);
        }
        return new DefaultHttpClient(new ThreadSafeClientConnManager());
    }
    
    /*
     * (non-Javadoc)
     */
    public HttpClient getHttpClient(Properties properties) {
        HttpParams params = new BasicHttpParams();
        String soTimeout = properties.getProperty(CoreConnectionPNames.SO_TIMEOUT);
        if (StringUtils.isNotEmpty(soTimeout)) {
            try {
                HttpConnectionParams.setSoTimeout(params,
                                                  Integer.parseInt(soTimeout));
            }
            catch (NumberFormatException e) {
                logger.error(CoreConnectionPNames.SO_TIMEOUT, e);
            }
        }
        
        String tcpNodelay = properties.getProperty(CoreConnectionPNames.TCP_NODELAY);
        if (StringUtils.isNotEmpty(tcpNodelay)) {
            HttpConnectionParams.setTcpNoDelay(params,
                                               Boolean.parseBoolean(tcpNodelay));
        }
        
        String socketBufferSize = properties.getProperty(CoreConnectionPNames.SOCKET_BUFFER_SIZE);
        if (StringUtils.isNotEmpty(socketBufferSize)) {
            try {
                HttpConnectionParams.setSocketBufferSize(params,
                                                         Integer.parseInt(socketBufferSize));
            }
            catch (NumberFormatException e) {
                logger.error(CoreConnectionPNames.SOCKET_BUFFER_SIZE, e);
            }
        }
        
        String soLinger = properties.getProperty(CoreConnectionPNames.SO_LINGER);
        if (StringUtils.isNotEmpty(soLinger)) {
            try {
                HttpConnectionParams.setLinger(params,
                                               Integer.parseInt(soLinger));
            }
            catch (NumberFormatException e) {
                logger.error(CoreConnectionPNames.SO_LINGER, e);
            }
        }
        
        String soReuseaddr = properties.getProperty(CoreConnectionPNames.SO_REUSEADDR);
        if (StringUtils.isNotEmpty(soReuseaddr)) {
            HttpConnectionParams.setSoReuseaddr(params,
                                                Boolean.parseBoolean(soReuseaddr));
        }
        
        String connectionTimeout = properties.getProperty(CoreConnectionPNames.CONNECTION_TIMEOUT);
        if (StringUtils.isNotEmpty(connectionTimeout)) {
            try {
                HttpConnectionParams.setConnectionTimeout(params,
                                                          Integer.parseInt(connectionTimeout));
            }
            catch (NumberFormatException e) {
                logger.error(CoreConnectionPNames.CONNECTION_TIMEOUT, e);
            }
        }
        
        String staleConnectionCheck = properties.getProperty(CoreConnectionPNames.STALE_CONNECTION_CHECK);
        if (StringUtils.isNotEmpty(staleConnectionCheck)) {
            HttpConnectionParams.setStaleCheckingEnabled(params,
                                                         Boolean.parseBoolean(staleConnectionCheck));
        }
        
        ThreadSafeClientConnManager connMgr = new ThreadSafeClientConnManager();
        String maxTotal = properties.getProperty(HttpClientFactory.CONNECTION_POOL_MAXSIZE);
        if (StringUtils.isNotEmpty(maxTotal)) {
            try {
                connMgr.setMaxTotal(Integer.parseInt(maxTotal));
            }
            catch (NumberFormatException e) {
                logger.error(HttpClientFactory.CONNECTION_POOL_MAXSIZE, e);
            }
        }
        
        return new DefaultHttpClient(connMgr, params);
    }
    
}
